﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;

namespace JESAI.Common.Util
{
    /// <summary>
    /// 加密处理类
    /// </summary>
    public sealed class Security
    {

        private static byte[] AesIV = { 0x41, 0x72, 0x65, 0x79, 0x6F, 0x75, 0x6D, 0x79, 0x53, 0x6E, 0x6F, 0x77, 0x6D, 0x61, 0x6E, 0x3F };

        #region 辅助方法

        /// <summary>
        /// 生成 Base64位干扰码
        /// </summary>
        /// <returns></returns>
        public static string CreateSaltKey()
        {
            byte[] data = new byte[8];
            new RNGCryptoServiceProvider().GetBytes(data);
            return Convert.ToBase64String(data);
        }
        /// <summary>
        /// 转换字符串为16进制字符串
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>16进制字符串</returns>
        public static string ToHex(string str) //返回处理后的十六进制字符串
        {
            return ToHex(Encoding.UTF8.GetBytes(str));
        }

        /// <summary>
        /// 转换byte数组为16进制字符串
        /// </summary>
        /// <param name="bytes">byte数组</param>
        /// <returns>16进制字符串</returns>
        public static string ToHex(byte[] bytes)
        {
            return BitConverter.ToString(bytes).Replace("-", "");
        }
        /// <summary>
        /// 合并字符串和干扰码
        /// </summary>
        /// <param name="str"></param>
        /// <param name="salt"></param>
        /// <returns></returns>
        public static byte[] MergeSalt(string str, string salt)
        {
            byte[] data = Encoding.UTF8.GetBytes(str);
            byte[] saltBytes = Convert.FromBase64String(salt);
            byte[] source = new byte[data.Length + saltBytes.Length];
            Buffer.BlockCopy(data, 0, source, 0, data.Length);
            Buffer.BlockCopy(saltBytes, 0, source, data.Length, saltBytes.Length);
            return source;
        }

        /// <summary>
        /// 生成 RSA 公钥私钥
        /// </summary>
        /// <returns></returns>
        public static string[] GenerateRSAKeys()
        {
            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
            return new string[] {
                  ToHex(rsaCryptoServiceProvider.ToXmlString(false)), //公钥
                  ToHex(rsaCryptoServiceProvider.ToXmlString(true))
            };
        }


        #endregion

        #region HashAlgorithm 哈希加密

        #region MD5

        /// <summary>
        /// MD5 加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string MD5(string str)
        {
            HashAlgorithm hashAlgorithm = HashAlgorithm.Create("MD5");
            byte[] bytes = Encoding.UTF8.GetBytes(str);
            byte[] securityBytes = hashAlgorithm.ComputeHash(bytes);
            return ToHex(securityBytes);
        }

        /// <summary>
        /// MD5 加密 
        /// </summary>
        /// <param name="str"></param>
        /// <param name="salt"></param>
        /// <returns></returns>
        public static string MD5(string str, string salt)
        {
            byte[] bytes = MergeSalt(str, salt);
            HashAlgorithm hashAlgorithm = HashAlgorithm.Create("MD5");
            byte[] securityBytes = hashAlgorithm.ComputeHash(bytes);
            return ToHex(securityBytes);
        }

        #endregion

        #region SHA256
        /// <summary>
        /// SHA256 加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string SHA256(string str)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(str);
            HashAlgorithm hashAlgorithm = HashAlgorithm.Create("SHA256");
            byte[] securityBytes = hashAlgorithm.ComputeHash(bytes);
            return Convert.ToBase64String(securityBytes);
        }

        /// <summary>
        ///  SHA256 加密 带干扰码
        /// </summary>
        /// <param name="str"></param>
        /// <param name="salt"></param>
        /// <returns></returns>
        public static string SHA256(string str, string salt)
        {
            byte[] bytes = MergeSalt(str, salt);
            HashAlgorithm hashAlgorithm = HashAlgorithm.Create("SHA256");
            byte[] securityBytes = hashAlgorithm.ComputeHash(bytes);
            return Convert.ToBase64String(securityBytes);
        }
        #endregion

        #endregion

        #region SymmetricAlgorithm 对称加密

        #region AES

        /// <summary>
        /// Aes加密 
        /// </summary>
        /// <param name="str">加密字符串</param>
        /// <param name="key">加密钥匙</param>
        /// <returns></returns>
        public static string AESEncrypt(string str, string key)
        {
            AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider();
            aesCryptoServiceProvider.Key = Encoding.UTF8.GetBytes(key);
            aesCryptoServiceProvider.IV = AesIV;

            byte[] inputBuffer = Encoding.UTF8.GetBytes(str);

            ICryptoTransform cryptoTransform = aesCryptoServiceProvider.CreateEncryptor();
            byte[] securityBytes = cryptoTransform.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
            return Convert.ToBase64String(securityBytes);
        }

        /// <summary>
        /// Aes解密
        /// </summary>
        /// <param name="base64Str"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string AESDecrypt(string base64Str, string key)
        {
            if (string.IsNullOrWhiteSpace(base64Str)) return "";

            byte[] securityBytes = Convert.FromBase64String(base64Str);
            try
            {
                AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider();
                aesCryptoServiceProvider.Key = Encoding.UTF8.GetBytes(key);
                aesCryptoServiceProvider.IV = AesIV;

                ICryptoTransform cryptoTransform = aesCryptoServiceProvider.CreateDecryptor();
                byte[] source = cryptoTransform.TransformFinalBlock(securityBytes, 0, securityBytes.Length);
                return Encoding.UTF8.GetString(source);
            }
            catch
            {
                return "";
            }
        }

        #endregion

        #endregion

        #region AsymmetricAlgorithm 非对称加密

        #region RSA
        /// <summary>
        /// 转换16进制为字符串
        /// </summary>
        /// <param name="hex">16进制</param>
        /// <returns>字符串</returns>
        public static string FromHex(string hexString)
        {
            return Encoding.UTF8.GetString(GetByteArrayFromHex(hexString));
        }
        public static byte[] GetByteArrayFromHex(string hexString)
        {
            hexString = hexString.Replace(" ", "");

            if (hexString.Length == 0)
                return new byte[] { };

            byte[] bytes = new byte[hexString.Length / 2];

            for (int i = 0; i < hexString.Length; i += 2)
            {
                if (!byte.TryParse(hexString.Substring(i, 2), NumberStyles.HexNumber, null, out bytes[i / 2]))
                    bytes[i / 2] = 0;
            }

            return bytes;
        }
        /// <summary>
        /// Ras 加密 
        /// </summary>
        /// <param name="str">加密字符串</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static string RSAEncrypt(string str, string publicKey)
        {
            try
            {
                RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
                byte[] bytes = Encoding.UTF8.GetBytes(str);
                rsaCryptoServiceProvider.FromXmlString(FromHex(publicKey));
                byte[] securityBytes = rsaCryptoServiceProvider.Encrypt(bytes, false);
                return Convert.ToBase64String(securityBytes);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        ///  RSA 解密 
        /// </summary>
        /// <param name="base64Str">解密字符串</param>
        /// <param name="privateKey">私钥</param>
        /// <returns></returns>
        public static string RSADecrypt(string base64Str, string privateKey)
        {
            try
            {
                RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
                rsaCryptoServiceProvider.FromXmlString(privateKey);
                byte[] securityBytes = Convert.FromBase64String(base64Str);
                byte[] source = rsaCryptoServiceProvider.Decrypt(securityBytes, false);
                return Encoding.UTF8.GetString(source);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #endregion

    }
}
